/**
 * Program : Lembar Kerja 04, Hierarchical Modelling
 *           Lighting, Shadow, and Texture, Worksheet 4
 * Berkas  : glutfunctions.h
 * ----------------------------------------------
 * Nama Pembuat :
 *  - Andry Luthfi, (0906629044)
 *  - Hadi Saputro, (0906562871)
 *
 * Aplikasi ini mengimplementasikan konsep Objek Hirarkis
 * serta teknik-teknik pencahayaan pada OpenGL. konsep-konsep
 * didapatkan pada mata kuliah Grafika Komputer.
 *
 * berkas ini berisikan fungsi-fungsi yang akan dirujukan kepada
 * fungsi pengendali pada Glut. berisikan fungsi-fungsi pengendali
 * event dan beberapa fungsi berjalan seperti fungsi penampilan,
 * fungsi ketika sedang lowong (idle) atau yang lainnya.
 *
 * Hak Cipta (c) 2012, Andry Luthfi, Hadi Saputro
 */

#include "display.h"

void glShadowProjection(float *, float *, float *);
void updRotationAngle();


/* fungsi reshape ketika ukuran window berubah2 */
static void functionReshape(int width, int height) {
    const float ratio = (float) width / (float) height;
    WINDOWS_HEIGHT = height;
    WINDOWS_WIDTH = width;

    glViewport(0, 0, width, height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    /* set view menjadi perspektif */
    gluPerspective(80.0,(float)width/(float)height,0.6,98.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

/* fungsi dipanggil untuk display semua komponen */
static void functionDisplay(void) {
    const double timeElapsed = glutGet(GLUT_ELAPSED_TIME) / 1000.0;
    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    changeView();

    glDisable(GL_LIGHTING);
    renderEnviroment();

    glEnable(GL_LIGHTING);
    glPushMatrix();
        glTranslatef(0.0, 0.0, 0.0);
        if (!isTexture_s) {
            glSetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess);
        }
        renderObjectSpider(); // menggambar objek spider
        renderShadowSpider();
    glPopMatrix();

    glEnable(GL_LIGHTING);
    glPushMatrix();
        glTranslatef(20.0, 0.0, -10.0);
        if (!isTexture_m) {
            glSetMaterial(mat_specular, mat_ambient, mat_diffuse, mat_shininess);
        }
        renderObjectMokuton(); // menggambar objek robot moku
        renderShadowMokuton();

        glEnable(GL_LIGHTING);
        renderTable();

    glPopMatrix();

    renderSomething();

    if (isTexture_m || isTexture_s) {
        textureOn();
    } else {
        glDisable(GL_TEXTURE_2D);
    }

    glFlush();
    glutSwapBuffers();
}

// fungsi handle menu;
static void handlerMenu(int id) {
    if (id == 11) isAnimated = !isAnimated;
    else if(id == 12) exit(0);
    functionDisplay();
    glutPostRedisplay();
}

// fungsi mouse listener
static void handlerMouse(int btn, int state, int x, int y) {
    if(btn==GLUT_LEFT_BUTTON && state == GLUT_DOWN) {
        theta[angle] += 5.0;
        mokuAngle[angle] +=5.0;
        if( theta[angle] > 360.0 ) {
            theta[angle] -= 360.0;
            mokuAngle[angle] -= 360.0;

        }
    }
    if(btn==GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
        theta[angle] -= 5.0;
        mokuAngle[angle] -=5.0;
        if( theta[angle] < 360.0 ) {
            theta[angle] += 360.0;
            mokuAngle[angle] +=360.0;
        }
    }
    functionDisplay();
}

// fungsi idle untuk animasi
static void functionIdle(void) {

    if(isAnimated) {
        light_angle += inc;
        mokuAngle[12] += inc*6;
        animateIdleMokuton();

        animateSpinningSpider();
        animateSpinningMokuton();
    }
    delay();

    if (mokutonAngle > 0.02) {
        mokutonAngle -= inc/2;
    } else if (mokutonAngle < -0.02) {
        mokutonAngle += inc/2;
    }

    if (light_angle >= 360) light_angle -= 360;
    if (mokuAngle[12] >= 360) mokuAngle[12] -= 360;
    glutPostRedisplay();
}

static void handlerKeyboard(unsigned char key, int x, int y) {
    isLight[(key - '1')] = !(isLight[(key - '1')]);
    switch(key) {
        case '1' :
            if (isLight[0]) glEnable(GL_LIGHT5);
            else glDisable(GL_LIGHT5);
            break;
        case '2' :
            if (isLight[1]) glEnable(GL_LIGHT0);
            else glDisable(GL_LIGHT0);
            break;
        case '3' :
            if (isLight[2]) glEnable(GL_LIGHT1);
            else glDisable(GL_LIGHT1);
            break;
        case '4' :
            if (isLight[3]) glEnable(GL_LIGHT2);
            else glDisable(GL_LIGHT2);
            break;


        case 'a' : case 'A' :
            if(cameraPositionX > -12.0) {
                cameraPositionX--;
                cameraLookX--;
            }
            break;

        case 'd' : case 'D' :
            if(cameraPositionX < 32.0) {
                cameraPositionX++;
                cameraLookX++;
            }
            break;


        case 'w' : case 'W' :
            if (cameraPositionZ > -29.0) {
                cameraPositionZ--;
                cameraLookZ--;
            }
            break;

        case 's' : case 'S' :
            if(cameraPositionZ < 29){
                cameraPositionZ++;
                cameraLookZ++;
            }
            break;

        case 'q' : case 'Q' :
            if (cameraPositionY > -8.0) {
                cameraPositionY--;
                cameraLookY--;
            }
            break;

        case 'e' : case 'E' :
            if(cameraPositionY < 14){
                cameraPositionY++;
                cameraLookY++;
            }
            break;

        case 'j' : case 'J':
            view = VIEW_ALL;
            functionDisplay();
            break;
        case 'k' : case 'K':
            view = VIEW_SPIDER;
            functionDisplay();
            break;
        case 'l' : case 'L':
            view = VIEW_MOKU;
            functionDisplay();
            break;

        case ']' : case '}' :
            if(!isAnimated) {
                light_angle += inc;
                if (light_angle >= 360) light_angle -= 360;
            }
            break;

        case '[' : case '{' :
            if(!isAnimated) {
                light_angle -= inc;
                if (light_angle <= 0) light_angle += 360;
            }
            break;

    }

    printf("[x: %2f, y: %2f, z: %2f]\n", cameraPositionX, cameraPositionY, cameraPositionZ);
}


static void handlerSpecialKeyboard(int key, int x, int y) {
    switch(key) {
        case GLUT_KEY_DOWN :
            if (mokutonAngle <= 30.0) {
                mokutonAngle += inc/1;
            }
            mokutonZ += inc/10;
            if (mokutonZ >=15) {
                mokuTogle = false;
            }
            break;

        case GLUT_KEY_UP :
            if (mokutonAngle >= -30.0) {
                mokutonAngle -= inc/1;
            }
            mokutonZ -= inc/10;
            if (mokutonZ <=-15) {
                mokuTogle = true;
            }
            break;

        case GLUT_KEY_LEFT :
            mokutonRot += inc*2;
            if (mokutonRot >= 360.0) {
                mokutonRot -= 360.0;
            }
            break;

        case GLUT_KEY_RIGHT :

            break;
    }
}
